package org.summer.lawyer.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.lock.annotation.Lock4j;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.summer.common.core.constant.Constants;
import org.summer.common.core.constant.UserConstants;
import org.summer.common.core.exception.ServiceException;
import org.summer.common.core.utils.MapstructUtils;
import org.summer.common.json.utils.JsonUtils;
import org.summer.common.mybatis.core.page.PageQuery;
import org.summer.common.mybatis.core.page.TableDataInfo;
import org.summer.lawyer.constant.LawFirmScopeConstants;
import org.summer.lawyer.constant.SystemConstants;
import org.summer.lawyer.domain.LawFirm;
import org.summer.lawyer.domain.WxUser;
import org.summer.lawyer.domain.bo.lawfirm.LawFirmBo;
import org.summer.lawyer.domain.bo.lawyerinfo.LawyerInfoBo;
import org.summer.lawyer.domain.bo.userfollow.UserFollowBo;
import org.summer.lawyer.domain.vo.lawfirm.LawFirmArchiveUpdateVo;
import org.summer.lawyer.domain.vo.lawfirm.LawFirmCreateVo;
import org.summer.lawyer.domain.vo.lawfirm.LawFirmUpdateVo;
import org.summer.lawyer.domain.vo.lawfirm.LawFirmVo;
import org.summer.lawyer.domain.vo.sysregion.SysRegionVo;
import org.summer.lawyer.domain.vo.userfollow.UserFollowVo;
import org.summer.lawyer.domain.vo.wxuser.WxUserCreateVo;
import org.summer.lawyer.domain.vo.wxuser.WxUserVo;
import org.summer.lawyer.event.LawFirmChangeEvent;
import org.summer.lawyer.mapper.LawFirmMapper;
import org.summer.lawyer.service.*;
import org.summer.lawyer.util.ParamsUtil;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 *
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LawFirmServiceImpl extends ServiceImpl<LawFirmMapper, LawFirm> implements ILawFirmService, ApplicationEventPublisherAware {

    private final IWxUserService wxUserService;
    private final ILawyerInfoService lawyerInfoService;
    private final IUserFollowService userFollowService;
    private final ISysRegionService sysRegionService;

    /**
     * 查询律所信息
     *
     * @param lawFirmId 主键
     * @return 律所信息
     */
    @Override
    public LawFirmVo selectLawFirmVoById(Long lawFirmId) {
        LawFirmVo lawFirmVo = baseMapper.selectVoById(lawFirmId);
        //获取管理员用户信息
        if (ObjectUtil.isNotNull(lawFirmVo)) {
            WxUserVo wxUserVo = wxUserService.selectWxUserVoById(lawFirmVo.getAdminUserId());
            if (ObjectUtil.isNotNull(wxUserVo)) {
                lawFirmVo.setNickname(wxUserVo.getNickname());
                lawFirmVo.setAccount(wxUserVo.getAccount());
            }
            //计算执业年限
            if(lawFirmVo.getYearServiceTime() != null){
                long year = DateUtil.betweenYear(lawFirmVo.getYearServiceTime(), DateUtil.date(), true);
                lawFirmVo.setPractice((int) year);
                lawFirmVo.setYears(lawFirmVo.getPractice());
            }
        }
        return lawFirmVo;
    }

    @Override
    public LawFirmVo selectLawFirmVoByAdminId(Long adminId) {
        LambdaQueryWrapper<LawFirm> lqw = Wrappers.lambdaQuery();
        lqw.eq(LawFirm::getAdminUserId, adminId);
        LawFirmVo lawFirmVo = baseMapper.selectVoOne(lqw, false);
        if (lawFirmVo != null) {
            return selectLawFirmVoById(lawFirmVo.getLawFirmId());
        }
        return null;
    }

    /**
     * 分页查询律所信息列表
     *
     * @param vo        查询条件
     * @param pageQuery 分页参数
     * @return 律所信息分页列表
     */
    @Override
    public TableDataInfo<LawFirmVo> selectPageList(LawFirmVo vo, PageQuery pageQuery) {
        QueryWrapper<LawFirm> lqw = buildQueryWrapper(vo);
        lqw.orderByDesc("lf.law_firm_id");
        Page<LawFirmVo> result = baseMapper.selectPageList(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<LawFirmVo> selectWechatPageList(LawFirmVo vo, PageQuery pageQuery) {
        vo.setStatus(UserConstants.NORMAL);
        QueryWrapper<LawFirm> lqw = buildQueryWrapper(vo);
        lqw.orderByDesc("lf.law_firm_id");
        Page<LawFirmVo> result = baseMapper.selectPageList(pageQuery.build(), lqw);
        TableDataInfo<LawFirmVo> tableDataInfo = TableDataInfo.build(result);
        if (CollUtil.isNotEmpty(tableDataInfo.getRows())) {
            for (LawFirmVo row : tableDataInfo.getRows()) {
                if (vo.getWxUserId() != null) {
                    //查询关注信息
                    UserFollowVo followVo = userFollowService.selectUserFollowVoByUserId(vo.getWxUserId(), row.getLawFirmId());
                    if (followVo != null && "0".equals(followVo.getCancelFlag())) {
                        row.setFollow("1");
                    }
                } else {
                    row.setFollow(SystemConstants.INACTIVE);
                }
                //计算执业年限
                row.setPractice(0);
                if(row.getYearServiceTime() != null){
                    long year = DateUtil.betweenYear(row.getYearServiceTime(), DateUtil.date(), true);
                    row.setPractice((int) year);
                    row.setYears(row.getPractice());
                }
            }
        }
        return tableDataInfo;
    }

    /**
     * 查询符合条件的律所信息列表
     *
     * @param vo 查询条件
     * @return 律所信息列表
     */
    @Override
    public List<LawFirmVo> selectLawFirmVoList(LawFirmVo vo) {
        QueryWrapper<LawFirm> lqw = buildQueryWrapper(vo);
        return baseMapper.selectVoList(lqw);
    }

    @Override
    public List<LawFirmVo> selectListByCurated() {
        LambdaQueryWrapper<LawFirm> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(LawFirm::getCurated, "1")
                .eq(LawFirm::getStatus, UserConstants.NORMAL)
                .orderByDesc(LawFirm::getRating);
        List<LawFirmVo> vos = baseMapper.selectVoList(queryWrapper);
        if(CollUtil.isNotEmpty(vos)){
            for (LawFirmVo vo : vos) {
                //计算执业年限
                vo.setPractice(0);
                if(vo.getYearServiceTime() != null){
                    long year = DateUtil.betweenYear(vo.getYearServiceTime(), DateUtil.date(), true);
                    vo.setPractice((int) year);
                    vo.setYears(vo.getPractice());
                }
            }
        }
        return vos;
    }

    private QueryWrapper<LawFirm> buildQueryWrapper(LawFirmVo vo) {
        Map<String, Object> params = ParamsUtil.getParams(vo.getParams());
        QueryWrapper<LawFirm> lqw = Wrappers.query();
        lqw.eq("lf.del_flag", Constants.DEL_FLAG_NOT_DEL);
       // lqw.like(StrUtil.isNotBlank(vo.getLawFirmName()),"lf.law_firm_name", vo.getLawFirmName());
        lqw.and(StrUtil.isNotBlank(vo.getLawFirmName()), qw -> qw.like("lf.law_firm_name",vo.getLawFirmName()).or().like("special", vo.getLawFirmName()));
        lqw.eq(StrUtil.isNotBlank(vo.getLawFirmType()), "lf.law_firm_type", vo.getLawFirmType());
        lqw.eq(StrUtil.isNotBlank(vo.getStatus()), "lf.status", vo.getStatus());
        lqw.like(StrUtil.isNotBlank(vo.getLawFirmAddress()), "lf.law_firm_address", vo.getLawFirmAddress());
        lqw.eq(StrUtil.isNotBlank(vo.getProvince()), "lf.province", vo.getProvince());
        lqw.eq(StrUtil.isNotBlank(vo.getProvinceId()), "lf.province_id", vo.getProvinceId());
        lqw.eq(StrUtil.isNotBlank(vo.getCity()), "lf.city", vo.getCity());
        lqw.eq(StrUtil.isNotBlank(vo.getCityId()), "lf.city_id", vo.getCityId());
        lqw.eq(StrUtil.isNotBlank(vo.getDistrict()), "lf.district", vo.getDistrict());
        lqw.eq(StrUtil.isNotBlank(vo.getDistrictId()), "lf.district_id", vo.getDistrictId());
        lqw.eq(vo.getAdminUserId() != null, "lf.admin_user_id", vo.getAdminUserId());
        lqw.eq(StrUtil.isNotBlank(vo.getCurated()), "lf.curated", vo.getCurated());
        lqw.eq(StrUtil.isNotBlank(vo.getCertification()), "lf.certification", vo.getCertification());
        lqw.like(StrUtil.isNotBlank(vo.getContactPhone()), "lf.contact_phone", vo.getContactPhone());
        lqw.like(StrUtil.isNotBlank(vo.getSpecial()), "lf.special", vo.getSpecial());
        lqw.between(params.get("beginTime") != null && params.get("endTime") != null, "lf.create_time", params.get("beginTime"), params.get("endTime"));
        return lqw;
    }

    /**
     * 新增律所信息
     *
     * @param vo 律所信息
     * @return 是否新增成功
     */
    @DSTransactional(rollbackFor = Exception.class)
    @Override
    public Boolean insertByVo(LawFirmCreateVo vo) {
        LawFirm add = MapstructUtils.convert(vo, LawFirm.class);
        validEntityBeforeSave(add);
        //创建默认用户信息
        WxUserCreateVo wxUserCreateVo = new WxUserCreateVo();
        wxUserCreateVo.setAccount(vo.getAccount());
        wxUserCreateVo.setAvatar(vo.getLawFirmLogo());
        wxUserCreateVo.setPassword(BCrypt.hashpw(vo.getPassword()));
        wxUserCreateVo.setPhoneNumber(vo.getContactPhone());
        wxUserCreateVo.setNickname(vo.getContactName());
        wxUserCreateVo.setCardName(vo.getLawFirmName());
        wxUserCreateVo.setCardPhone(vo.getContactPhone());
        wxUserCreateVo.setWxUserType(SystemConstants.WX_USER_TYPE_LAWYER);
        wxUserService.createWxUser(wxUserCreateVo);
        this.updateRegionData(add);
        add.setAdminUserId(wxUserCreateVo.getWxUserId());
        add.setStatus(UserConstants.USER_NORMAL);
        add.setCreateTime(DateUtil.date());
        add.setRating(new BigDecimal("0"));
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            vo.setLawFirmId(add.getLawFirmId());
        }
        //创建默认律师
//        if (LawFirmScopeConstants.LAWYER.equals(vo.getLawFirmType())) {
//            LawyerInfoBo lawyerInfoBo = new LawyerInfoBo();
//            lawyerInfoBo.setLawFirmId(vo.getLawFirmId());
//            lawyerInfoBo.setLawyerName(vo.getLawFirmName());
//            lawyerInfoBo.setAvatar(vo.getLawFirmLogo());
//            lawyerInfoBo.setPracticeStartTime(vo.getYearServiceTime());
//            lawyerInfoBo.setWxUserId(wxUserCreateVo.getWxUserId());
//            lawyerInfoBo.setGroupType(LawFirmScopeConstants.LAWYER);
//            lawyerInfoBo.setPractice(0);
//            lawyerInfoBo.setAdviceStatus(vo.getCurated());
//            lawyerInfoBo.setFollowers(0);
//            lawyerInfoBo.setConsultation(0);
//            lawyerInfoBo.setLawyerDesc(vo.getLawFirmDesc());
//            lawyerInfoBo.setSpecial(vo.getSpecial());
//            lawyerInfoService.insertByBo(lawyerInfoBo);
//        }
        LawFirmVo lawFirmVo = selectLawFirmVoById(add.getLawFirmId());
        WxUserVo wxUserVo = wxUserService.selectWxUserVoById(add.getAdminUserId());
        applicationEventPublisher.publishEvent(new LawFirmChangeEvent(this, lawFirmVo, wxUserVo));
        return flag;
    }

    /**
     * 修改律所信息
     *
     * @param vo 律所信息
     * @return 是否修改成功
     */
    @DSTransactional(rollbackFor = Exception.class)
    @Override
    public Boolean updateByVo(LawFirmUpdateVo vo) {
        LawFirm update = MapstructUtils.convert(vo, LawFirm.class);
        validEntityBeforeSave(update);
        WxUserVo wxUserVo = wxUserService.selectWxUserVoById(vo.getAdminUserId());
        wxUserVo.setAvatar(vo.getLawFirmLogo());
        wxUserVo.setNickname(vo.getLawFirmName());
        WxUser wxUser = MapstructUtils.convert(wxUserVo, WxUser.class);
        wxUserService.updateById(wxUser);
//        if(LawFirmScopeConstants.LAWYER.equals(vo.getLawFirmType())){
//            //查询是否存在
//        }
        this.updateRegionData(update);
        boolean flag = baseMapper.updateById(update) > 0;
        LawFirmVo lawFirmVo = selectLawFirmVoById(vo.getLawFirmId());
        applicationEventPublisher.publishEvent(new LawFirmChangeEvent(this, lawFirmVo, wxUserVo));
        return flag;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(LawFirm entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除律所信息信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @DSTransactional(rollbackFor = Exception.class)
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        //删除登录用户
        List<Long> userIds = CollUtil.newArrayList();
        for (Long id : ids) {
            LawFirmVo lawFirmVo = selectLawFirmVoById(id);
            userIds.add(lawFirmVo.getAdminUserId());
        }
        wxUserService.deleteWithValidByIds(userIds, true);
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public void updateLawFirmArchive(LawFirmArchiveUpdateVo vo) {
        LawFirmVo lawFirmVo = selectLawFirmVoById(vo.getLawFirmId());
        if (lawFirmVo == null) {
            throw new ServiceException("信息未找到");
        }
        LambdaUpdateWrapper<LawFirm> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(LawFirm::getLawFirmId, vo.getLawFirmId())
                .set(LawFirm::getLawFirmDesc, vo.getLawFirmDesc())
                .set(LawFirm::getSpecial, vo.getSpecial())
                .set(LawFirm::getLawFirmAddress, vo.getLawFirmAddress());
        baseMapper.update(updateWrapper);
        if (LawFirmScopeConstants.LAWYER.equals(lawFirmVo.getLawFirmType())) {
            //更新律师信息
            LawyerInfoBo lawyerInfoBo = new LawyerInfoBo();
            lawyerInfoBo.setLawFirmId(vo.getLawFirmId());
            lawyerInfoBo.setLawyerDesc(vo.getLawFirmDesc());
            lawyerInfoBo.setSpecial(vo.getSpecial());
            lawyerInfoBo.setOfficeAddress(vo.getLawFirmAddress());
            lawyerInfoService.updateLawyerArchive(lawyerInfoBo);
        }
    }

    @Override
    public boolean checkPhoneUnique(LawFirmVo vo) {
        return baseMapper.exists(new LambdaQueryWrapper<LawFirm>()
                .eq(LawFirm::getContactPhone, vo.getContactPhone())
                .ne(ObjectUtil.isNotNull(vo.getLawFirmId()), LawFirm::getLawFirmId, vo.getLawFirmId()));
    }

    @Override
    public boolean checkLawFirmNameUnique(LawFirmVo vo) {
        return baseMapper.exists(new LambdaQueryWrapper<LawFirm>()
                .eq(LawFirm::getLawFirmName, vo.getLawFirmName())
                .ne(ObjectUtil.isNotNull(vo.getLawFirmId()), LawFirm::getLawFirmId, vo.getLawFirmId()));
    }

    @DSTransactional(rollbackFor = Exception.class)
    @Override
    public void changeLawFirmStatus(LawFirmBo bo) {
        LambdaUpdateWrapper<LawFirm> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(LawFirm::getLawFirmId, bo.getLawFirmId())
                .set(LawFirm::getStatus, bo.getStatus())
                .set(LawFirm::getUpdateTime, DateUtil.date());
        baseMapper.update(updateWrapper);
        //更新微信用户状态
        LawFirmVo lawFirmVo = selectLawFirmVoById(bo.getLawFirmId());
        WxUserVo wxUserVo = new WxUserVo();
        wxUserVo.setWxUserId(lawFirmVo.getAdminUserId());
        wxUserVo.setStatus(bo.getStatus());
        wxUserService.changeWxUserStatus(wxUserVo);
    }

    @Override
    public void followLawFirm(UserFollowBo bo) {
        log.info("[followLawFirm]关注律所,参数:{}", JsonUtils.toJsonString(bo));
        //查询律所信息
        LawFirmVo lawFirmVo = selectLawFirmVoById(bo.getFolloweeId());
        if (lawFirmVo == null) {
            throw new ServiceException("关注对象信息未找到");
        }
        bo.setFolloweeScope(lawFirmVo.getLawFirmType());
        bo.setFolloweeName(lawFirmVo.getLawFirmName());
        bo.setAvatar(lawFirmVo.getLawFirmLogo());
        bo.setFolloweeDesc(lawFirmVo.getLawFirmDesc());
        //查询用户信息
        WxUserVo wxUserVo = wxUserService.selectWxUserVoById(bo.getWxUserId());
        if (wxUserVo == null) {
            throw new ServiceException("用户未找到");
        }
        bo.setFollowName(wxUserVo.getNickname());
        bo.setFollowAvatar(wxUserVo.getAvatar());
        userFollowService.follow(bo);
        //更新粉丝数量
        this.updateLawFirmFollowCount(lawFirmVo.getLawFirmId(), 1);
    }

    @Override
    public void unfollowLawFirm(UserFollowBo bo) {
        UserFollowVo userFollowVo = userFollowService.selectUserFollowVoByUserId(bo.getWxUserId(), bo.getFolloweeId());
        if (userFollowVo != null) {
            userFollowService.unfollow(bo);
            //更新粉丝数量
            this.updateLawFirmFollowCount(userFollowVo.getFolloweeId(), -1);
        }

    }

    @Lock4j(keys = "{#lawFirmId}", acquireTimeout = 1000, expire = 10000)
    @Override
    public void updateLawFirmFollowCount(Long lawFirmId, Integer followCount) {
        LawFirmVo lawFirmVo = selectLawFirmVoById(lawFirmId);
        if (lawFirmVo != null) {
            Integer count = lawFirmVo.getFollowers() == null ? 0 : lawFirmVo.getFollowers();
            count += followCount;
            if(count < 0){
                count = 0;
            }
            LawFirm lawFirm = new LawFirm();
            lawFirm.setLawFirmId(lawFirmId);
            lawFirm.setFollowers(count);
            LambdaUpdateWrapper<LawFirm> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.eq(LawFirm::getLawFirmId, lawFirmId);
            baseMapper.update(lawFirm, updateWrapper);
        }
    }

    private ApplicationEventPublisher applicationEventPublisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    private void updateRegionData(LawFirm lawFirm) {
        //处理区域数据
        if (StrUtil.isNotBlank(lawFirm.getCityId())) {
            SysRegionVo regionCity = sysRegionService.selectSysRegionVoById(lawFirm.getCityId());
            if (regionCity != null && regionCity.getRegionLevel() == 2L) {
                lawFirm.setCity(regionCity.getRegionName());
                // SysRegionVo regionCity = sysRegionService.selectSysRegionVoById(regionDistrict.getPid());
               // if (regionCity != null) {
                 //   lawFirm.setCity(regionCity.getRegionName());
              //      lawFirm.setCityId(regionCity.getId());
                    SysRegionVo regionProvince = sysRegionService.selectSysRegionVoById(regionCity.getPid());
                    if (regionProvince != null) {
                        lawFirm.setProvince(regionProvince.getRegionName());
                        lawFirm.setProvinceId(regionProvince.getId());
                    }
             //   }
            }else{
                throw new ServiceException("请选择二级地区数据");
            }
        }
    }

    @Override
    public void updateRating(Long lawFirmId, BigDecimal rating) {
        LawFirm lawFirm = new LawFirm();
        lawFirm.setLawFirmId(lawFirmId);
        lawFirm.setRating(rating);
        LambdaUpdateWrapper<LawFirm> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(LawFirm::getLawFirmId, lawFirmId);
        baseMapper.update(lawFirm, updateWrapper);
    }

    /**
     * 律所排名
     */
    @Override
    public List<LawFirmVo> selectListByRating(LawFirmBo bo) {
        LambdaQueryWrapper<LawFirm> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(LawFirm::getStatus, UserConstants.NORMAL)
                .eq(LawFirm::getLawFirmType, LawFirmScopeConstants.LAW_FIRM)
                .orderByDesc(LawFirm::getRating);
        return baseMapper.selectVoList(queryWrapper);
    }
}
